
// <copyright file="NetworkConnectionDialer.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The connection type.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.Net
{
    using System;
    using System.Runtime.InteropServices;

    #region Enumerations

    /// <summary>
    /// The connection type.
    /// </summary>
    public enum ConnectionType
    {
        /// <summary>
        /// The lan.
        /// </summary>
        Lan = 0, 

        /// <summary>
        /// The modem.
        /// </summary>
        Modem = 1, 

        /// <summary>
        /// The proxy.
        /// </summary>
        Proxy = 2, 

        /// <summary>
        /// The not connected.
        /// </summary>
        NotConnected = 3
    }

    /// <summary>
    /// The disconnect result.
    /// </summary>
    public enum DisconnectResult
    {
        /// <summary>
        /// The disconnected.
        /// </summary>
        Disconnected = 0, 

        /// <summary>
        /// The could not disconnect.
        /// </summary>
        CouldNotDisconnect = 1, 

        /// <summary>
        /// The no active connection to disconnect.
        /// </summary>
        NoActiveConnectionToDisconnect = 2
    }

    #endregion Enumerations

    /// <summary>
    /// The network connection dialer.
    /// </summary>
    public class NetworkConnectionDialer
    {
        #region Constants

        /// <summary>
        /// The erro r_ invali d_ parameter.
        /// </summary>
        private const int ERROR_INVALID_PARAMETER = 0X87;

        /// <summary>
        /// The erro r_ success.
        /// </summary>
        private const int ERROR_SUCCESS = 0X0;

        #endregion Constants

        #region Fields

        /// <summary>
        /// The connection name.
        /// </summary>
        private readonly string _connectionName;

        /// <summary>
        /// The ml connection.
        /// </summary>
        private int mlConnection;

        #endregion Fields

        #region Constructors and Finalizers

        /// <summary>
        /// Initializes a new instance of the <see cref="NetworkConnectionDialer"/> class.
        /// </summary>
        /// <param name="connectionName">
        /// The connection name.
        /// </param>
        public NetworkConnectionDialer(string connectionName)
        {
            this._connectionName = connectionName;
        }

        #endregion Constructors and Finalizers

        // Declaration Used For InternetDialUp.
        #region Enums

        /// <summary>
        /// The dial up options.
        /// </summary>
        private enum DialUpOptions
        {
            /// <summary>
            /// The interne t_ dia l_ unattended.
            /// </summary>
            INTERNET_DIAL_UNATTENDED = 0X8000, 

            /// <summary>
            /// The interne t_ dia l_ sho w_ offline.
            /// </summary>
            INTERNET_DIAL_SHOW_OFFLINE = 0X4000, 

            /// <summary>
            /// The interne t_ dia l_ forc e_ prompt.
            /// </summary>
            INTERNET_DIAL_FORCE_PROMPT = 0X2000
        }

        /// <summary>
        /// The flags.
        /// </summary>
        private enum Flags
        {
            // Local system uses a LAN to connect to the Internet.
            /// <summary>
            /// The interne t_ connectio n_ lan.
            /// </summary>
            INTERNET_CONNECTION_LAN = 0X2, 

            // Local system uses a modem to connect to the Internet.
            /// <summary>
            /// The interne t_ connectio n_ modem.
            /// </summary>
            INTERNET_CONNECTION_MODEM = 0X1, 

            // Local system uses a proxy server to connect to the Internet.
            /// <summary>
            /// The interne t_ connectio n_ proxy.
            /// </summary>
            INTERNET_CONNECTION_PROXY = 0X4, 

            // Type Visual Basic 6 code here...

            // Local system has RAS installed.
            /// <summary>
            /// The interne t_ ra s_ installed.
            /// </summary>
            INTERNET_RAS_INSTALLED = 0X10
        }

        #endregion Enums

        // Return the Connection info as a sting value
        #region Public Properties

        /// <summary>
        /// Gets a value indicating whether is connected.
        /// </summary>
        public static bool IsConnected
        {
            get
            {
                int Desc = 0;
                return NativeMethods.InternetGetConnectedState(ref Desc, 0);
            }
        }

        #endregion Public Properties

        #region Public Methods and Operators

        /// <summary>
        /// The connect.
        /// </summary>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool Connect()
        {
            int DResult = NativeMethods.InternetDial(IntPtr.Zero, this._connectionName, Convert.ToInt32(DialUpOptions.INTERNET_DIAL_UNATTENDED), ref this.mlConnection, 0);
            return DResult == ERROR_SUCCESS;
        }

        /// <summary>
        /// The connect.
        /// </summary>
        /// <param name="maxNumberOfAttempts">
        /// The max number of attempts.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// </exception>
        public bool Connect(int maxNumberOfAttempts)
        {
            if (maxNumberOfAttempts <= 0)
            {
                throw new ArgumentException(@"maxNumberOfAttempts must be greater than zero", "maxNumberOfAttempts");
            }

            for (int i = 0; i < maxNumberOfAttempts || maxNumberOfAttempts < 1; )
            {
                if (this.Connect())
                {
                    return true;
                }

                if (maxNumberOfAttempts > 0)
                {
                    i++;
                }
            }

            return false;
        }

        /// <summary>
        /// The disconnect.
        /// </summary>
        /// <returns>
        /// The <see cref="DisconnectResult"/>.
        /// </returns>
        public DisconnectResult Disconnect()
        {
            if (this.mlConnection != 0)
            {
                int result = NativeMethods.InternetHangUp(this.mlConnection, 0);
                return result == 0 ? DisconnectResult.CouldNotDisconnect : DisconnectResult.Disconnected;
            }

            return DisconnectResult.NoActiveConnectionToDisconnect;
        }

        /// <summary>
        /// The get connection type.
        /// </summary>
        /// <returns>
        /// The <see cref="ConnectionType"/>.
        /// </returns>
        public ConnectionType GetConnectionType()
        {
            int lngFlags = 0;

            if (NativeMethods.InternetGetConnectedState(ref lngFlags, 0))
            {
                // connected.
                if ((lngFlags & (int)Flags.INTERNET_CONNECTION_LAN) != 0)
                {
                    // LAN connection.
                    return ConnectionType.Lan;
                }

                if ((lngFlags & (int)Flags.INTERNET_CONNECTION_MODEM) != 0)
                {
                    // Modem connection.
                    return ConnectionType.Modem;
                }

                if ((lngFlags & (int)Flags.INTERNET_CONNECTION_PROXY) != 0)
                {
                    // Proxy connection.
                    return ConnectionType.Proxy;
                }

                return ConnectionType.NotConnected;
            }

            return ConnectionType.NotConnected;
        }

        #endregion Public Methods and Operators

        /// <summary>
        /// The native methods.
        /// </summary>
        private static class NativeMethods
        {
            #region Methods

            /// <summary>
            /// The internet dial.
            /// </summary>
            /// <param name="hwndParent">
            /// The hwnd parent.
            /// </param>
            /// <param name="lpszConnectoid">
            /// The lpsz connectoid.
            /// </param>
            /// <param name="dwFlags">
            /// The dw flags.
            /// </param>
            /// <param name="lpdwConnection">
            /// The lpdw connection.
            /// </param>
            /// <param name="dwReserved">
            /// The dw reserved.
            /// </param>
            /// <returns>
            /// The <see cref="int"/>.
            /// </returns>
            [DllImport("Wininet.dll", EntryPoint = "InternetDial", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern int InternetDial(IntPtr hwndParent, string lpszConnectoid, int dwFlags, ref int lpdwConnection, int dwReserved);

            /// <summary>
            /// The internet get connected state.
            /// </summary>
            /// <param name="lpdwFlags">
            /// The lpdw flags.
            /// </param>
            /// <param name="dwReserved">
            /// The dw reserved.
            /// </param>
            /// <returns>
            /// The <see cref="bool"/>.
            /// </returns>
            [DllImport("wininet.dll", EntryPoint = "InternetGetConnectedState", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern bool InternetGetConnectedState(ref int lpdwFlags, int dwReserved);

            /// <summary>
            /// The internet hang up.
            /// </summary>
            /// <param name="lpdwConnection">
            /// The lpdw connection.
            /// </param>
            /// <param name="dwReserved">
            /// The dw reserved.
            /// </param>
            /// <returns>
            /// The <see cref="int"/>.
            /// </returns>
            [DllImport("Wininet.dll", EntryPoint = "InternetHangUp", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern int InternetHangUp(int lpdwConnection, int dwReserved);

            #endregion Methods
        }
    }
}
